package com.xbongbong.saas.model.impl;

import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.PaymentErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.PaymentBalanceInsertConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.dao.PaymentBalanceDao;
import com.xbongbong.saas.domain.entity.PaymentBalanceEntity;
import com.xbongbong.saas.enums.business.PaymentBalanceEnum;
import com.xbongbong.saas.model.PaymentBalanceModel;
import org.elasticsearch.action.support.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 梁鲁江
 * @version v1.0
 * @date 2019/11/7 10:15
 * @since v1.0
 */
@Service("paymentBalanceModel")
public class PaymentBalanceModelImpl implements PaymentBalanceModel {
    @Resource
    private PaymentBalanceDao  paymentBalanceDao;
    @Resource
    private PaasEsModel paasEsModel;
    public static final Logger LOG = LoggerFactory.getLogger(PaymentBalanceModelImpl.class);
    @Override
    public Integer save(PaymentBalanceEntity entity)  throws XbbException{
        Long id = entity.getId();
        if (id == null || id == 0L) {
            return   insert(entity);
        }
        return update(entity);
    }

    @Override
    public PaymentBalanceEntity getByCustomerId(Long customerId, String corpid) throws XbbException {
        return paymentBalanceDao.getByCustomerId(customerId,corpid);
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer insert(PaymentBalanceEntity entity) throws XbbException {
        Double advancePaymentBalance = entity.getAdvancePaymentBalance();
        if (advancePaymentBalance == null || Objects.equals(BasicConstant.ZERO_DOUBLE, advancePaymentBalance)) {
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208033);
        }
        long now = DateTimeUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        Integer insert = null;
        try {
            paymentBalanceDao.insert(entity);
            insert =PaymentBalanceInsertConstant.INSERT;
        } catch (Exception e) {
            String str = "Duplicate entry";
            String str1 = "for key 'idx_corpid_customer'";
            String message = e.getCause().getMessage();
            //如果是唯一键重复，则进行更新处理
            if(message.contains(str) && message.contains(str1)){
                paymentBalanceDao.updatePaymentBalanceDelByCorpidAndCustomerId(entity.getAdvancePaymentBalance(),entity.getCorpid(),entity.getCustomerId());
                insert =PaymentBalanceInsertConstant.UPDATE;
            }else{
                throw  e;
            }
        }
        entity = getByCustomerId(entity.getCustomerId(),entity.getCorpid());
        if(entity.getAdvancePaymentBalance() < 0 ){
            throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208041);
        }
        InsertDTO insertDTO = getSaveDTO(entity,IndexTypeEnum.IDX_PAYMENT_BALANCE);
        paasEsModel.insert(insertDTO);
        return insert;
    }

    @Override
    public Integer update(PaymentBalanceEntity entity) throws XbbException {
        return null;
    }

    @Override
    public PaymentBalanceEntity getById(Long id, String corpid) throws XbbException {
        return paymentBalanceDao.getByKey(id,corpid);
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer update(PaymentBalanceEntity entity,boolean updateDel) throws XbbException {
        Double advancePaymentBalance = entity.getAdvancePaymentBalance();
        if (advancePaymentBalance == null || Objects.equals(BasicConstant.ZERO_DOUBLE, advancePaymentBalance)) {
            throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208033);
        }
        Integer balance;
        Long id = entity.getId();
        if (id == null || id == 0L) {
            balance = paymentBalanceDao.updatePaymentBalanceByCorpidAndCustomerId(advancePaymentBalance, entity.getCorpid(), entity.getCustomerId());
        }else{
            if(updateDel){
                balance = paymentBalanceDao.updatePaymentBalanceDelByCorpidAndId(advancePaymentBalance,entity.getCorpid(),entity.getId());
            }else {
                balance = paymentBalanceDao.updatePaymentBalanceByCorpidAndId(advancePaymentBalance,entity.getCorpid(),entity.getId());
            }
        }
        entity = getByCustomerId(entity.getCustomerId(),entity.getCorpid());
        if(entity.getAdvancePaymentBalance() < 0 ){
            throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208041);
        }
        InsertDTO insertDTO = getSaveDTO(entity,IndexTypeEnum.IDX_PAYMENT_BALANCE);
        paasEsModel.update(insertDTO);
        return balance;
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer updatePaymentBalanceById(PaymentBalanceEntity entity) throws XbbException {
        Double advancePaymentBalance = entity.getAdvancePaymentBalance();
        if (advancePaymentBalance == null ) {
            advancePaymentBalance = 0D;
        }
        Long id = entity.getId();
        Integer balance = paymentBalanceDao.updatePaymentBalanceById(advancePaymentBalance, entity.getCorpid(), id);
        entity = getByCustomerId(entity.getCustomerId(),entity.getCorpid());
        if(entity.getAdvancePaymentBalance() < 0 ){
            throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208041);
        }
        InsertDTO insertDTO = getSaveDTO(entity,IndexTypeEnum.IDX_PAYMENT_BALANCE);
        paasEsModel.update(insertDTO);
        return balance;
    }

    @Override
    public List findEntitys(Map<String, Object> param) {
        return paymentBalanceDao.findEntitys(param);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return paymentBalanceDao.getEntitysCount(param);
    }

    @Override
    public List findEntitysWithoutSub(Map<String, Object> param) {
        return null;
    }

    @Override
    public InsertDTO getSaveDTO(PaymentBalanceEntity paymentBalanceEntity, IndexTypeEnum indexTypeEnum) throws XbbException {
        InsertDTO insertDTO = new InsertDTO();
        //customerId也可以做主键
        insertDTO.setEsId(paymentBalanceEntity.getCorpid() + "_" + paymentBalanceEntity.getId());
        insertDTO.setSource(BeanUtil.convertBean2Map(paymentBalanceEntity, false, true));
        insertDTO.setIndexTypeEnum(indexTypeEnum);
        return insertDTO;
    }
    
    /**
     * 根据客户IDList获取余额
     *
     * @param customerIds
     * @param corpid
     * @return
     * @throws XbbException
     */
    @Override
    public List<PaymentBalanceEntity> getByCustomerIds(Collection<Long> customerIds, String corpid) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("customerIds", customerIds);
        param.put("corpid", corpid);
        param.put("del", 0);
        return findEntitys(param);
    }

    private List<PaymentBalanceEntity> getByCustomerIds(List<Long> customerIds, String corpid,String columns) throws XbbException {
        return paymentBalanceDao.getByCustomerIds(customerIds,corpid,columns);
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer updateBatchByCorpidAndCustomerId(List<PaymentBalanceEntity> list, String corpid) throws XbbException {
        if (list.size() == 0) {
            return BasicConstant.ZERO;
        }
        Integer integer = null;
        try {
            integer = paymentBalanceDao.updateBatchByCorpidAndCustomerId(list, corpid);
            List<Long> customerIds = new ArrayList<>(list.size());
            for (PaymentBalanceEntity paymentBalanceEntity : list) {
                customerIds.add(paymentBalanceEntity.getCustomerId());
            }
            list = getByCustomerIds(customerIds,corpid,"id,corpid,advance_payment_balance,update_time");
            List<InsertDTO> insertList = new ArrayList<>();
            for (PaymentBalanceEntity paymentBalanceEntity : list) {
                if(paymentBalanceEntity.getAdvancePaymentBalance() < 0 ){
                    throw  new XbbException(PaymentErrorCodeEnum.API_ERROR_208041);
                }
                InsertDTO insertDTO = new InsertDTO();
                insertDTO.setEsId(corpid + "_" + paymentBalanceEntity.getId());
                Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put(PaymentBalanceEnum.ADVANCE_PAYMENT_BALANCE.getAttr(),paymentBalanceEntity.getAdvancePaymentBalance());
                map.put(PaymentBalanceEnum.UPDATE_TIME.getAttr(),paymentBalanceEntity.getUpdateTime());
                insertDTO.setSource(map);
                insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAYMENT_BALANCE);
                insertList.add(insertDTO);
            }
            //保证更新ES是最后一行，如果不能要在catch写ES的回滚
            paasEsModel.updateBatch(insertList);
        } catch (XbbException e) {
            LOG.error(PaymentErrorCodeEnum.API_ERROR_208044.getMsg(),e);
            throw e;
        }catch (Exception e){
            LOG.error(PaymentErrorCodeEnum.API_ERROR_208044.getMsg(),e);
            throw e;
        }
        return integer;
    }

    /**
     * 删除预收款余额记录（保证余额=0才能删除）
     * @param idIn
     * @param corpid
     * @return
     */
    @Override
    public Integer deleteBatch(List<Long> idIn, String corpid) throws XbbException {
        Integer delete = 0;
        if(CollectionsUtil.isEmpty(idIn)){
            return delete;
        }
        try {
            delete = paymentBalanceDao.deleteBatch(idIn, corpid);
            updateDel(idIn, corpid,DelEnum.DELETE.getDel());
        } catch (XbbException e) {
            throw e;
        }
        return delete;
    }

    @Override
    public Integer deleteBatchRollback(List<Long> idIn, String corpid) throws XbbException {
        Integer delete = 0;
        if(CollectionsUtil.isEmpty(idIn)){
            return delete;
        }
        try {
            //回滚ES，不需要修改数据库，数据库已经回滚
            updateDel(idIn, corpid,DelEnum.NORMAL.getDel());
        } catch (XbbException e) {
            throw e;
        }
        return 1;
    }

    private void updateDel(List<Long> idIn, String corpid,Integer del) throws XbbException {
        List<InsertDTO> insertList = new ArrayList<>();
        for (Long aLong : idIn) {
            InsertDTO insertDTO = new InsertDTO();
            insertDTO.setEsId(corpid + "_" + aLong);
            Map<String, Object> map = new HashMap<>(2);
            map.put(StringConstant.DEL, del);
            map.put(PaymentBalanceEnum.UPDATE_TIME.getAttr(), DateUtil.getNow());
            insertDTO.setSource(map);
            insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAYMENT_BALANCE);
            insertList.add(insertDTO);
        }
        //保证更新ES是最后一行，如果不能要在catch写ES的回滚
        paasEsModel.updateBatch(insertList);
    }

    @Override
    public void updateBatchAdvance(String corpid, List<PaymentBalanceEntity> list) throws XbbException {
        paymentBalanceDao.updateBatchAdvanceByCorpidAndCustomerId(list, corpid);
        //处理es
        List<InsertDTO> insertList = new ArrayList<>();
        for (PaymentBalanceEntity balanceEntity : list) {
            Map<String,Object> map = new HashMap<>();
            map.put("advancePaymentBalance", balanceEntity.getAdvancePaymentBalance());
            InsertDTO insertDTO = new InsertDTO();
            insertDTO.setEsId(corpid + "_" + balanceEntity.getId());
            insertDTO.setSource(map);
            insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAYMENT_BALANCE);
            insertList.add(insertDTO);
        }
        //保证更新ES是最后一行，如果不能要在catch写ES的回滚
        paasEsModel.updateBatch(insertList);
    }


    @Override
    public Integer updateTime(Long id,String corpid) throws XbbException {
        long now = DateUtil.getInt();
        // 更新时间
        Integer success = paymentBalanceDao.updateTime(now, id, corpid);
        // 更新es
        PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
        paasFormDataEntity.setId(id);
        paasFormDataEntity.setDataId(id);
        paasFormDataEntity.setCorpid(corpid);
        paasFormDataEntity.setUpdateTime(now);
        InsertDTO insertDTO = paasEsModel.getSaveDTO(paasFormDataEntity, IndexTypeEnum.IDX_PAYMENT_BALANCE);
        paasEsModel.update(insertDTO);
        return success;
    }

    @Override
    public Integer updateBatch(List<UpdateDataEntity> list, String corpid) throws XbbException {
        Integer integer = 0;
        if (CollectionsUtil.isNotEmpty(list)) {
            integer = paymentBalanceDao.updateBatch(list, corpid);
            paasEsModel.updateBatchMuchField(list, IndexTypeEnum.IDX_PAYMENT_BALANCE);
        }
        return integer;
    }

    @Override
    public Integer updateBatch(List<UpdateDataEntity> list, String corpid, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        Integer integer = 0;
        if (CollectionsUtil.isEmpty(list)) {
            return integer;
        }
        integer = paymentBalanceDao.updateBatch(list, corpid);
        paasEsModel.updateBatchMuchField(list, IndexTypeEnum.IDX_PAYMENT_BALANCE, refreshPolicy);
        return integer;
    }
}
